/*
 * Copyright 2010-2012 Susanta Tewari. <freecode4susant@users.sourceforge.net>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package genomemap.data;

import java.util.*;

/**
 * @author stewari1
 * @version 1.0
 * @created 03-Nov-2007 4:19:35 PM
 */
public class Clone extends DNA_Region implements Comparable<Clone> {

    /**
     * A clone that is not repeated, that is present in only 1 chromosome.
     */
    public static final int S_CLONE = 0;

    /**
     *  A clone that is repeated on more than 1 chromosome
     */
    public static final int R_CLONE = 1;

    /**
     * A clone that is repeated on all chromosomes
     */
    public static final int A_CLONE = 2;

    /**
     * Chromosomes this clone is present in.
     */
    private Set<Integer> linkageGroupSet = new HashSet<>();

    /**
     * collection of clones that hybridize to this clone
     */
    private final Set<Clone> linkedClonesSet = new HashSet<>();

    /**
     * set of genes that are tagged (overlapping as defined in {@link DNA_Region}) to
     * this clone.
     */
    private Set<Gene> taggedGeneSet = new HashSet<>();

    /**
     * true if this clone is a Probe
     */
    private boolean probe = false;

    /**
     * Constructs ...
     */
    public Clone() {
        setType(DNA_Region.CLONE_TYPE);
    }

    /**
     *
     * @param clone
     * @return
     */
    public int compareTo(Clone clone) {

        int diff = this.getOrder() - clone.getOrder();

        return diff;
    }

    /**
     *
     * @param gene
     */
    public void addTaggedGene(Gene gene) {
        getTaggedGeneSet().add(gene);
    }

    public void removeAllTaggedGenes() {
        getTaggedGeneSet().clear();
    }

    /**
     * attempts to add a linkage group to a clone.
     * @param ch_id must be a positive. for example, linkage group 1 is denoted by 1
     * not 0
     */
    public void addLinkageGroup(int ch_id) {
        if (ch_id > 0) getLinkageGroupSet().add(new Integer(ch_id));
    }

    public boolean isProbe() {
        return probe;
    }

    public void setProbe(boolean newVal) {
        probe = newVal;
    }

    public Set<Gene> getTaggedGeneSet() {
        return taggedGeneSet;
    }

    public void setTaggedGeneSet(Set<Gene> newVal) {
        taggedGeneSet = newVal;
    }

    public int getCloneType() {

        if (isSClone()) return S_CLONE;
        if (isRClone()) return R_CLONE;
        if (isAClone()) return A_CLONE;


        // if hasn`t returned yet.. that means linkage groups have not been set
        System.out.println("From Clone.getCloneType()");
        System.out.println("type information is not available for clone: " + getLabel());
        System.out.println("linkage groups size : " + getLinkageGroupSet().size());

        return -1;    // indicating error
    }

    public boolean isProbe(Probe probe) {
        return probe.getLabel().equals(getLabel());
    }

    public boolean isSClone() {
        return getLinkageGroupSet().size() == 1;
    }

    public boolean isRClone() {
        return (getLinkageGroupSet().size() > 1) && (getLinkageGroupSet().size() < 7);
    }

    public boolean isAClone() {
        return getLinkageGroupSet().size() == 7;
    }

    /**
     * checks if this clone has linked clones. This is a convenience method
     * that in turn checks if the private variable <code>linkedClonesSet</code> is empty.
     * @return true if and only if this clone has no linking (overlapping ? )clones.
     */
    public boolean isLinked() {
        return !linkedClonesSet.isEmpty();
    }

    /**
     * checks if this clone has any tagged (overlapping in region) gene. This is a
     * convenience method that in turn checks if the set returned by method
     * <code>getTaggedGeneSet</code> is emplty.
     * @return true if and only if this clone has no tagged genes.
     */
    public boolean isTagged() {
        return !taggedGeneSet.isEmpty();
    }

    public Set<Integer> getLinkageGroupSet() {
        return linkageGroupSet;
    }

    public void setLinkageGroupSet(Set<Integer> linkageGroupSet) {
        this.linkageGroupSet = linkageGroupSet;
    }
}
